package com.ybkj.o2o.mc.manager.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ybkj.o2o.mc.common.AccountUtils;
import com.ybkj.o2o.mc.common.Arith;
import com.ybkj.o2o.mc.common.DataGrid;
import com.ybkj.o2o.mc.common.query.PassengerQuery;
import com.ybkj.o2o.mc.common.query.PassengerQuery2;
import com.ybkj.o2o.mc.entity.Passenger;
import com.ybkj.o2o.mc.entity.PassengerAccount;
import com.ybkj.o2o.mc.entity.PassengerGrade;
import com.ybkj.o2o.mc.manager.PassengerManager;
import com.ybkj.o2o.mc.service.PassengerAccountService;
import com.ybkj.o2o.mc.service.PassengerAddressService;
import com.ybkj.o2o.mc.service.PassengerConcatsService;
import com.ybkj.o2o.mc.service.PassengerGradeService;
import com.ybkj.o2o.mc.service.PassengerService;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.*;


/**
 * Created by shine on 15/8/19.
 */
@Service
public class DefaultPassengerManager implements PassengerManager {

    @Autowired
    private PassengerService passengerService;

    @Autowired
    private PassengerAddressService passengerAddressService;

    @Autowired
    private PassengerConcatsService passengerConcatsService;

    @Autowired
    private PassengerAccountService passengerAccountService;

    @Autowired
    private PassengerGradeService passengerGradeService;

    @Override
    public Passenger fetch(Long id) {

        return passengerService.fetch(id);
    }

    @Override
    public boolean existsByPhone(String phone, String appKey) {
        return passengerService.existsByPhone(phone, appKey);
    }

    @Override
    public boolean existsByIdcard(String idcard, String appKey) {
        return passengerService.existsByIdcard(idcard, appKey);
    }

    @Override
    public boolean existsByEmail(String email, String appKey) {
        return passengerService.existsByEmail(email, appKey);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Passenger insert(Passenger passenger) {
        passengerService.insert(passenger);
        return passenger;
    }

    @Override
    public Passenger findByPhoneAndAppKey(String phone, String appKey) {

        return passengerService.findByPhoneAndAppKey(phone, appKey);
    }

    @Override
    public Passenger findByEmailAndAppKey(String email, String appKey) {

        return passengerService.findByEmailAndAppKey(email, appKey);
    }

    @Override
    public Passenger findByIdcardAndAppKey(String idcard, String appKey) {

        return passengerService.findByIdcardAndAppKey(idcard, appKey);
    }

    @Override
    public Passenger findByJobNumberAndAppKey(String jobNumber, String appKey) {
        return passengerService.findByJobNumberAndAppKey(jobNumber, appKey);
    }

    @Override
    public Passenger findByNameAndAppKey(String name, String appKey) {
        return passengerService.findByJobNumberAndAppKey(name, appKey);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(Passenger passenger) {

        return passengerService.update(passenger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByDate(Passenger passenger) {

        return passengerService.updateByDate(passenger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePassenger(Long passengerId, String appKey) {

        Passenger passenger = passengerService.findByIdAndAppKey(passengerId, appKey);

        if (null != passenger) {
            passengerAddressService.deleteByPassenger(passengerId);
            passengerConcatsService.deleteByPassenger(passengerId);
            //passengerAccountService.deleteByPassenger(passengerId);

            return passengerService.delete(passengerId, appKey);
        }

        return 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateLocation(Passenger passenger) {
        passenger.setUpdated(new Date());
        return passengerService.updateLocation(passenger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateBlackList(Passenger passenger) {
        passenger.setUpdated(new Date());
        return passengerService.updateBlackList(passenger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDeviceType(Passenger passenger) {
        passenger.setUpdated(new Date());
        return passengerService.updateDeviceType(passenger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateReceiptMoney(Passenger passenger) {
        passenger.setUpdated(new Date());
        return passengerService.updateBalance(passenger);
    }


    @Override
    public DataGrid<Passenger> findByPassengerQuery(PassengerQuery passengerQuery) {

        List<Passenger> list = passengerService.findByPassengerQuery(passengerQuery);

        long count = passengerService.countByPassengerQuery(passengerQuery);

        DataGrid<Passenger> dataGrid = new DataGrid<>();
        dataGrid.setRows(list);
        dataGrid.setTotal(count);

        return dataGrid;
    }

    @Override
    public long countByPassengerQuery(PassengerQuery passengerQuery) {

        return passengerService.countByPassengerQuery(passengerQuery);
    }

    @Override
    public Passenger findByIdAndAppKey(Long passengerId, String appKey) {

        Passenger passenger = passengerService.findByIdAndAppKey(passengerId, appKey);
        if (passenger != null) {
            PassengerGrade passengerGrade = passengerGradeService.fetch(passenger.getGradeId(), passenger.getCompanyId(), appKey);
            passenger.setPassengerGrade(passengerGrade);
        }

        return passenger;
    }

    @Override
    public List<String> findChannels(String appKey) {
        return passengerService.findChannels(appKey);
    }

    @Override
    public double sumDrawMoney(Long companyId, String name, String appKey) {

        if (StringUtils.isNotBlank(name)) {
            name = "%" + name + "%";
        }

        return passengerService.sumDrawMoney(companyId, name, appKey);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public PassengerAccount updateAccount(PassengerAccount account, Passenger passenger,
                                          Boolean updateBlance, Boolean useNoDrawMoney) {

        if (updateBlance) {

            AccountUtils.recharge(account, passenger, useNoDrawMoney);
            int ret2 = passengerService.updateBalance(passenger);
            if (ret2 != 1) {
                throw new RuntimeException("账户信息更新失败");
            }
        }

        account.setAfterDrawMoney(passenger.getDrawMoney());
        account.setAfterNoDrawMoney(passenger.getNodrawMoney());
        account.setCreated(new Date());
        account.setUpdated(new Date());
        account.setVersion(1);

        int ret = passengerAccountService.insert(account);
        if (ret != 1) {
            throw new RuntimeException("账户记录保存失败");
        }

        return account;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PassengerAccount updateNoDrawMoney(PassengerAccount account, Passenger passenger,
                                              Boolean updateBlance) {

        if (updateBlance) {
            passenger.setNodrawMoney(Arith.add(passenger.getNodrawMoney(), account.getMoney()));
            int ret = passengerService.updateBalance(passenger);
            if (ret != 1) {
                throw new RuntimeException("账户余额信息更新失败");
            }
        }

        account.setAfterDrawMoney(passenger.getDrawMoney());
        account.setAfterNoDrawMoney(passenger.getNodrawMoney());
        account.setCreated(new Date());
        account.setUpdated(new Date());
        account.setVersion(1);
        int ret = passengerAccountService.insert(account);
        if (ret != 1) {
            throw new RuntimeException("账户记录保存失败");
        }

        return account;
    }


    @Override
    public List<Passenger> findByTypeOrCompanyId(Integer type, Long companyId, String appKey) {
        return passengerService.findByTypeOrCompanyId(type, companyId, appKey);
    }

    @Override
    public DataGrid<Passenger> findByPassengerQuery2(PassengerQuery2 passengerQuery) {

        List<Passenger> list = passengerService.findByPassengerQuery2(passengerQuery);
        long count = passengerService.countByPassengerQuery2(passengerQuery);

        DataGrid<Passenger> dataGrid = new DataGrid<>();
        dataGrid.setRows(list);
        dataGrid.setTotal(count);

        return dataGrid;
    }

    @Override
    public Long countByPassengerQuery2(PassengerQuery2 passengerQuery2) {

        return passengerService.countByPassengerQuery2(passengerQuery2);
    }

    @Override
    public DataGrid<Passenger> findByPassengerQuery3(PassengerQuery2 passengerQuery) {

        List<Passenger> list = passengerService.findByPassengerQuery3(passengerQuery);
        long count = passengerService.countByPassengerQuery3(passengerQuery);

        DataGrid<Passenger> dataGrid = new DataGrid<>();
        dataGrid.setRows(list);
        dataGrid.setTotal(count);

        return dataGrid;
    }

    @Override
    public Long countByPassengerQuery3(PassengerQuery2 passengerQuery2) {

        return passengerService.countByPassengerQuery3(passengerQuery2);
    }

    @Override
    public List<Passenger> findByEnterprise(Long enterpriseId, String appKey) {

        return passengerService.findByEnterpriseAndAppkey(enterpriseId, appKey);
    }

    @Override
    public boolean existsByPhones(List<String> phones, String appKey) {

        List<Passenger> passengers = passengerService.findByPhones(phones, appKey);

        return !CollectionUtils.isEmpty(passengers);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchInsert(List<Passenger> passengers) {

        return passengerService.batchInsert(passengers);
    }

    @Override
    public int updateCompanyName(Long companyId, String abbreviation, String appKey) {

        return passengerService.updateCompanyName(companyId, abbreviation, appKey);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> batchCreate(String passengers, String appKey) {
        Gson gson = new Gson();
        Map<String, Object> data = new HashMap<>();
        List<Passenger> list = gson.fromJson(
                passengers, new TypeToken<List<Passenger>>() {
                }.getType());
        PassengerGrade defaultByCompanyId =
                passengerGradeService.findDefaultByCompanyId(
                        list.get(0).getCompanyId(), appKey);
        List<Passenger> list2 = new LinkedList<>();
        int phoneCount = 0;
        for (Passenger passenger : list) {
            Passenger byPhoneAndAppKey =
                    passengerService.findByPhoneAndAppKey(passenger.getPhone(), appKey);
            if (byPhoneAndAppKey != null) {
                phoneCount++;
                continue;
            }
            if (defaultByCompanyId != null) {
                passenger.setGradeId(defaultByCompanyId.getId());
                passenger.setGradeName(defaultByCompanyId.getName());
            }

            passenger.setChannelName("电话预约");
            passenger.setType(0);
            passenger.setGender(1);
            passenger.setDrawMoney(0.0);
            passenger.setNodrawMoney(0.0);
            passenger.setFrozenMoney(0.0);
            passenger.setAppKey(appKey);
            list2.add(passenger);
        }
        if (!CollectionUtils.isEmpty(list2)) {
            passengerService.batchInsert(list2);
        }
        data.put("phoneCount", phoneCount);
        data.put("rows", list2.size());
        return data;
    }

    @Override
    public List<Passenger> findByGradeId(Long gradeId, String appKey) {

        return passengerService.findByGradeId(gradeId, appKey);
    }

    @Override
    public int disposeGrade(Long gradeId, String gradeName, Long companyId, String appKey) {

        return passengerService.disposeGrade(gradeId, gradeName, companyId, appKey);
    }

    @Override
    public DataGrid<Passenger> findByIds(PassengerQuery passengerQuery) {
        DataGrid<Passenger> dataGrid = new DataGrid<Passenger>();
        List<Passenger> list = passengerService.findByIds(passengerQuery);
        Long count = passengerService.countByIds(passengerQuery);
        dataGrid.setRows(list);
        dataGrid.setTotal(count);
        return dataGrid;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchDeleteByIds(List<Long> passengerIds, String appKey) {
        return passengerService.batchDelete(passengerIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByDelDepartment(Long id, String appKey) {
        return passengerService.updateByDelDepartment(id, appKey);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchUpdateByIds(List<Long> passengerIds, String appKey) {
        return passengerService.batchUpdateByIds(passengerIds, appKey);
    }

    @Override
    public int updateEnterpriseName(Long enterpriseId, String enterpriseName, String appKey) {
        return passengerService.updateEnterpriseName(enterpriseId, enterpriseName, appKey);
    }

    @Override
    public int updateDepartmentName(Long departmentId, String departmentName, String appKey) {
        return passengerService.updateDepartmentName(departmentId, departmentName, appKey);
    }

    @Override
    public int updateGradeByEnterpriseId(Long enterpriseId, Long gradeId,
                                         String gradeName, String appKey) {
        return passengerService.updateGradeByEnterpriseId(enterpriseId, gradeId, gradeName, appKey);
    }

    @Override
    public int updateAllowOverdraw(Long enterpriseId, Boolean allowOverdraw, String appKey) {
        return passengerService.updateAllowOverdraw(enterpriseId, allowOverdraw, appKey);
    }

    @Override
    public Long findByIntroduceType(Integer introduceType, String introducer, Integer companyId, String appKey) {
        return passengerService.findByIntroduceType(introduceType, introducer, companyId, appKey);
    }

    public int updateChannel(String appKey, String channelName, Long id) {
        return passengerService.updateChannel(channelName, id, appKey);
    }


    public List<Map<String, Object>> findWeixinInfoByIds(List<Long> ids) {
        Collections.sort(ids, Comparator.naturalOrder());
        List<Map<String, Object>> weixinInfoByIds = passengerService.findWeixinInfoByIds(ids);
        if (null != weixinInfoByIds && 0 != weixinInfoByIds.size()) {
            for (int i = 0, j = 0; i < weixinInfoByIds.size(); i++) {
                Map<String, Object> map = weixinInfoByIds.get(i);
                Long id = Long.valueOf(map.get("id").toString());
                try {
                    Object wxHeadImgUrlObject = map.get("wxHeadImgUrl");
                    if (null == wxHeadImgUrlObject || wxHeadImgUrlObject.toString().trim().equals("")) {
                        String phone = map.get("phone").toString();
                        Map<String, String> kv = new HashMap<>();
                        kv.put("phones", phone);

                        String jsonStr = restTemplate.getForObject(getWxBasePath() + GET_WX_USER_INFO_BY_PHONES, String.class, kv);
                        JSONObject obj = JSON.parseObject(jsonStr);
                        if (null != obj) {
                            Boolean success = obj.getBoolean("success");
                            if (success.booleanValue()) {
                                JSONObject data = obj.getJSONObject("data");
                                if (null != data) {
                                    String headimgurl = data.getString("headimgurl");
                                    String nickname = data.getString("nickname");
                                    if (null != headimgurl) {
                                        passengerService.updateWxInfoByPhone(headimgurl, nickname, phone);
                                    }
                                }
                            }
                        }

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
        return weixinInfoByIds;
    }

    @Value("${spring.wxUrl}")
    private String wxUrl;

    @Autowired
    private RestTemplate restTemplate;

    public static final String GET_WX_USER_INFO_BY_PHONES = "api/getWxUserInfoByPhones?phones={phones}";

    public String getWxBasePath() {
        if (wxUrl.endsWith("/") || wxUrl.endsWith("\\")) {
            return wxUrl;
        } else {
            return wxUrl + "/";
        }
    }
}
